package com.jnc.web.util.gen;

import cn.hutool.core.date.DateUtil;
import com.jnc.common.constant.SysConstant;
import com.jnc.common.util.convert.StringUtil;
import com.jnc.core.properties.GlobalProperties;
import com.jnc.web.biz.tool.model.ColumnInfo;
import com.jnc.web.biz.tool.model.TableInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * @Author: jjn
 * @Date: 2018/11/14
 * @Desc: 代码生成器工具类
 */
@Slf4j
@Component
@EnableConfigurationProperties(GlobalProperties.class)
public class GenUtil {

    @Autowired
    GlobalProperties globalProperties;

    /** 项目空间路径 */
    private static final String PROJECT_PATH = "main/java/com/jnc";
    /** mybatis空间路径 */
    private static final String MYBATIS_PATH = "main/resources/mybatis";
    /** html空间路径 */
    private static final String HTML_PATH = "main/resources/templates";
    /** 类型转换 */
    private static Map<String, String> javaTypeMap = new HashMap<>();

    /**
     * 设置列信息
     * @param columns
     * @return
     */
    public List<ColumnInfo> transColumns(List<ColumnInfo> columns){
        List<ColumnInfo> columnList = new ArrayList<>();
        for (ColumnInfo column : columns){
            //列名转换成java属性名
            String attrName = StringUtil.toUpperCamelCase(column.getColumnName());
            column.setAttrName(attrName);
            column.setAttrname(StringUtils.uncapitalize(attrName));

            //列的数据类型，转换成Java类型
            String attrType = javaTypeMap.get(column.getDataType());
            column.setAttrType(attrType);

            columnList.add(column);
        }
        return columnList;
    }

    /**
     * 初始化模板参数
     * @param tableInfo
     * @return
     */
    public VelocityContext getVelocityContext(TableInfo tableInfo){
        //java对象数据传递到模板文件 vm
        VelocityContext velocityContext = new VelocityContext();
        String packageName = globalProperties.getPackageName();
        velocityContext.put("tableName", tableInfo.getTableName());
        velocityContext.put("tableComment", replaceKeyword(tableInfo.getTableComment()));
        velocityContext.put("primaryKey", tableInfo.getPrimaryKey());
        velocityContext.put("className", tableInfo.getClassName());
        velocityContext.put("classname", tableInfo.getClassname());
        velocityContext.put("moduleName", getModuleName(packageName));
        velocityContext.put("columns", tableInfo.getColumns());
        velocityContext.put("package", packageName);
        velocityContext.put("author", globalProperties.getAuthor());
        velocityContext.put("date", DateUtil.formatDate(new Date()));
        return velocityContext;
    }

    /**
     * 获取模板列表
     * @return
     */
    public List<String> getTemplates(){
        List<String> templates = new ArrayList<>();
        templates.add("vm/java/Model.java.vm");
        templates.add("vm/java/Mapper.java.vm");
        templates.add("vm/java/Service.java.vm");
        templates.add("vm/java/ServiceImpl.java.vm");
        templates.add("vm/java/Controller.java.vm");
        templates.add("vm/xml/Mapper.xml.vm");
        templates.add("vm/html/add.html.vm");
        templates.add("vm/html/edit.html.vm");
        templates.add("vm/html/list.html.vm");
        return templates;
    }

    /**
     * 表名转换成Java类名(首字母大写)
     * @param tableName
     * @return
     */
    public String tableToJava(String tableName){
        if(SysConstant.AUTO_REMOVE_TABLE_NAME_PRE.equals(globalProperties.getAutoRemoveTableNamePre())){
            tableName = tableName.substring(tableName.indexOf("_") + 1);
        }
        if(StringUtils.isNotBlank(globalProperties.getTablePrefix())){
            tableName = tableName.replace(globalProperties.getTablePrefix(), "");
        }
        return StringUtil.toUpperCamelCase(tableName);
    }

    /**
     * 获取文件名
     * @param template
     * @param tableInfo
     * @param moduleName
     * @return
     */
    public String getFileName(String template, TableInfo tableInfo, String moduleName){
        //小写类名
        String classname = tableInfo.getClassname();
        //大写类名
        String className = tableInfo.getClassName();
        String javaPath = PROJECT_PATH + "/" + moduleName + "/";
        String mybatisPath = MYBATIS_PATH + "/" + moduleName + "/" + classname;
        String htmlPath = HTML_PATH + "/" + moduleName + "/" + classname;
        if(template.contains("Model.java.vm")){
            return javaPath + "model" + "/" + className + ".java";
        }
        if(template.contains("Mapper.java.vm")){
            return javaPath + "mapper" + "/" + className + "Mapper.java";
        }
        if(template.contains("Service.java.vm")){
            return javaPath + "service" + "/" + className + "Service.java";
        }
        if(template.contains("ServiceImpl.java.vm")){
            return javaPath + "service" + "/" + "impl" + "/" + className + "ServiceImpl.java";
        }
        if(template.contains("Controller.java.vm")){
            return javaPath + "controller" + "/" + className + "Controller.java";
        }
        if(template.contains("Mapper.xml.vm")){
            return mybatisPath + ".xml";
        }
        if(template.contains("add.html.vm")){
            return htmlPath + "/" + "add.html";
        }
        if(template.contains("edit.html.vm")){
            return htmlPath + "/" + "edit.html";
        }
        if(template.contains("list.html.vm")){
            return htmlPath + "/" + "list.html";
        }
        return null;
    }


    /**
     * 去除格式字符串
     * @param keyword
     * @return
     */
    private String replaceKeyword(String keyword){
        String keyName = keyword.replaceAll("(?:表|信息)", "");
        return keyName;
    }

    /**
     * 获取模块名
     * @param packageName 包名
     * @return 模块名
     */
    public String getModuleName(String packageName){
        int lastIndex = packageName.lastIndexOf(".");
        int nameLength = packageName.length();
        String moduleName = StringUtils.substring(packageName, lastIndex + 1, nameLength);
        return moduleName;
    }

    //初始化数据库数据类型和java数据类型map
    static {
        javaTypeMap.put("tinyint", "Integer");
        javaTypeMap.put("smallint", "Integer");
        javaTypeMap.put("mediumint", "Integer");
        javaTypeMap.put("int", "Integer");
        javaTypeMap.put("integer", "integer");
        javaTypeMap.put("bigint", "Long");
        javaTypeMap.put("float", "Float");
        javaTypeMap.put("double", "Double");
        javaTypeMap.put("decimal", "BigDecimal");
        javaTypeMap.put("bit", "Boolean");
        javaTypeMap.put("char", "String");
        javaTypeMap.put("varchar", "String");
        javaTypeMap.put("tinytext", "String");
        javaTypeMap.put("text", "String");
        javaTypeMap.put("mediumtext", "String");
        javaTypeMap.put("longtext", "String");
        javaTypeMap.put("time", "Date");
        javaTypeMap.put("date", "Date");
        javaTypeMap.put("datetime", "Date");
        javaTypeMap.put("timestamp", "Date");
    }

}
